#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
问卷生成工具 - GUI界面
支持Excel文件转JSON格式的问卷，带配置管理和批量处理功能
"""

import tkinter as tk
from tkinter import ttk, filedialog, messagebox, scrolledtext
import json
import os
import sys
import threading
from pathlib import Path
from typing import Dict, List, Any
import pandas as pd

# 导入转换器
from excel_to_json_converter import QuestionnaireConverter


class QuestionnaireGUI:
    """问卷转换器GUI主类"""
    
    def __init__(self, root):
        self.root = root
        self.root.title("问卷生成工具 - Excel转JSON")
        self.root.geometry("1000x700")
        
        # 配置文件和路径
        self.config_file = "converter_config.json"
        self.excel_folder = ""
        self.output_folder = ""
        self.converter = QuestionnaireConverter()
        
        # 当前Excel文件列表
        self.excel_files = []
        
        # 创建界面
        self.create_widgets()
        self.load_config()
        self.refresh_file_list()
    
    def create_widgets(self):
        """创建GUI组件"""
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 配置区域
        config_frame = ttk.LabelFrame(main_frame, text="配置设置", padding="5")
        config_frame.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10))
        
        # Excel文件夹选择
        ttk.Label(config_frame, text="Excel文件夹:").grid(row=0, column=0, sticky=tk.W, padx=(0, 5))
        self.excel_folder_var = tk.StringVar()
        excel_folder_entry = ttk.Entry(config_frame, textvariable=self.excel_folder_var, width=50)
        excel_folder_entry.grid(row=0, column=1, sticky=(tk.W, tk.E), padx=(0, 5))
        ttk.Button(config_frame, text="浏览", command=self.select_excel_folder).grid(row=0, column=2)
        
        # 输出文件夹选择
        ttk.Label(config_frame, text="输出文件夹:").grid(row=1, column=0, sticky=tk.W, padx=(0, 5), pady=(5, 0))
        self.output_folder_var = tk.StringVar()
        output_folder_entry = ttk.Entry(config_frame, textvariable=self.output_folder_var, width=50)
        output_folder_entry.grid(row=1, column=1, sticky=(tk.W, tk.E), padx=(0, 5), pady=(5, 0))
        ttk.Button(config_frame, text="浏览", command=self.select_output_folder).grid(row=1, column=2, pady=(5, 0))
        
        # 保存配置按钮
        ttk.Button(config_frame, text="保存配置", command=self.save_config).grid(row=2, column=0, pady=(10, 0))
        ttk.Button(config_frame, text="刷新文件列表", command=self.refresh_file_list).grid(row=2, column=1, pady=(10, 0))
        
        # 文件列表区域
        file_frame = ttk.LabelFrame(main_frame, text="Excel文件列表", padding="5")
        file_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 10))
        
        # 文件列表树形视图
        columns = ("文件名", "大小", "修改时间", "状态")
        self.file_tree = ttk.Treeview(file_frame, columns=columns, show="headings", height=8)
        
        # 设置列标题
        for col in columns:
            self.file_tree.heading(col, text=col)
            self.file_tree.column(col, width=150)
        
        # 滚动条
        file_scrollbar = ttk.Scrollbar(file_frame, orient=tk.VERTICAL, command=self.file_tree.yview)
        self.file_tree.configure(yscrollcommand=file_scrollbar.set)
        
        # 布局
        self.file_tree.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        file_scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
        
        # 操作按钮区域
        button_frame = ttk.Frame(file_frame)
        button_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(10, 0))
        
        ttk.Button(button_frame, text="转换选中文件", command=self.convert_selected).pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(button_frame, text="转换所有文件", command=self.convert_all).pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(button_frame, text="清空输出", command=self.clear_output).pack(side=tk.LEFT, padx=(0, 5))
        
        # 进度条
        self.progress_var = tk.DoubleVar()
        self.progress_bar = ttk.Progressbar(button_frame, variable=self.progress_var, maximum=100)
        self.progress_bar.pack(side=tk.LEFT, padx=(10, 0), fill=tk.X, expand=True)
        
        # 日志区域
        log_frame = ttk.LabelFrame(main_frame, text="转换日志", padding="5")
        log_frame.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        self.log_text = scrolledtext.ScrolledText(log_frame, height=10, width=80)
        self.log_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 配置网格权重
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)
        main_frame.columnconfigure(1, weight=1)
        main_frame.rowconfigure(1, weight=1)
        config_frame.columnconfigure(1, weight=1)
        file_frame.columnconfigure(0, weight=1)
        file_frame.rowconfigure(0, weight=1)
        log_frame.columnconfigure(0, weight=1)
        log_frame.rowconfigure(0, weight=1)
    
    def log_message(self, message: str):
        """添加日志消息"""
        self.log_text.insert(tk.END, f"{message}\n")
        self.log_text.see(tk.END)
        self.root.update_idletasks()
    
    def select_excel_folder(self):
        """选择Excel文件夹"""
        folder = filedialog.askdirectory(title="选择Excel文件夹")
        if folder:
            self.excel_folder_var.set(folder)
            self.excel_folder = folder
            self.refresh_file_list()
    
    def select_output_folder(self):
        """选择输出文件夹"""
        folder = filedialog.askdirectory(title="选择输出文件夹")
        if folder:
            self.output_folder_var.set(folder)
            self.output_folder = folder
    
    def save_config(self):
        """保存配置到JSON文件"""
        config = {
            "excel_folder": self.excel_folder_var.get(),
            "output_folder": self.output_folder_var.get()
        }
        
        try:
            with open(self.config_file, 'w', encoding='utf-8') as f:
                json.dump(config, f, ensure_ascii=False, indent=2)
            self.log_message("配置已保存")
        except Exception as e:
            messagebox.showerror("错误", f"保存配置失败: {str(e)}")
    
    def load_config(self):
        """从JSON文件加载配置"""
        try:
            if os.path.exists(self.config_file):
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    config = json.load(f)
                    self.excel_folder_var.set(config.get("excel_folder", ""))
                    self.output_folder_var.set(config.get("output_folder", ""))
                    self.excel_folder = config.get("excel_folder", "")
                    self.output_folder = config.get("output_folder", "")
        except Exception as e:
            self.log_message(f"加载配置失败: {str(e)}")
    
    def refresh_file_list(self):
        """刷新文件列表"""
        self.file_tree.delete(*self.file_tree.get_children())
        self.excel_files = []
        
        excel_folder = self.excel_folder_var.get()
        if not excel_folder or not os.path.exists(excel_folder):
            return
        
        try:
            for file_path in Path(excel_folder).glob("*.xlsx"):
                file_stat = file_path.stat()
                file_size = f"{file_stat.st_size / 1024:.1f} KB"
                mod_time = file_path.stat().st_mtime
                mod_time_str = pd.Timestamp.fromtimestamp(mod_time).strftime("%Y-%m-%d %H:%M")
                
                self.file_tree.insert("", tk.END, values=(
                    file_path.name,
                    file_size,
                    mod_time_str,
                    "待转换"
                ))
                self.excel_files.append(str(file_path))
            
            self.log_message(f"找到 {len(self.excel_files)} 个Excel文件")
        except Exception as e:
            self.log_message(f"刷新文件列表失败: {str(e)}")
    
    def convert_selected(self):
        """转换选中的文件"""
        selected_items = self.file_tree.selection()
        if not selected_items:
            messagebox.showwarning("警告", "请先选择要转换的文件")
            return
        
        if not self.output_folder_var.get():
            messagebox.showwarning("警告", "请先选择输出文件夹")
            return
        
        # 在新线程中执行转换
        thread = threading.Thread(target=self._convert_files, args=(selected_items,))
        thread.daemon = True
        thread.start()
    
    def convert_all(self):
        """转换所有文件"""
        if not self.excel_files:
            messagebox.showwarning("警告", "没有找到Excel文件")
            return
        
        if not self.output_folder_var.get():
            messagebox.showwarning("警告", "请先选择输出文件夹")
            return
        
        # 在新线程中执行转换
        thread = threading.Thread(target=self._convert_all_files)
        thread.daemon = True
        thread.start()
    
    def _convert_files(self, selected_items):
        """转换指定文件（在后台线程中执行）"""
        total_files = len(selected_items)
        success_count = 0
        
        for i, item in enumerate(selected_items):
            try:
                # 获取文件路径
                file_name = self.file_tree.item(item, "values")[0]
                file_path = os.path.join(self.excel_folder, file_name)
                
                # 更新状态
                self.root.after(0, lambda: self.file_tree.set(item, "状态", "转换中..."))
                
                # 执行转换
                output_path = os.path.join(self.output_folder, file_name.replace('.xlsx', '.json'))
                self.converter.convert_excel_to_json(file_path, output_path)
                
                # 更新状态
                self.root.after(0, lambda: self.file_tree.set(item, "状态", "转换成功"))
                self.root.after(0, lambda: self.log_message(f"转换成功: {file_name}"))
                success_count += 1
                
            except Exception as e:
                self.root.after(0, lambda: self.file_tree.set(item, "状态", "转换失败"))
                self.root.after(0, lambda: self.log_message(f"转换失败: {file_name} - {str(e)}"))
            
            # 更新进度条
            progress = ((i + 1) / total_files) * 100
            self.root.after(0, lambda p=progress: self.progress_var.set(p))
        
        # 转换完成
        self.root.after(0, lambda: self.log_message(f"批量转换完成: {success_count}/{total_files} 成功"))
        self.root.after(0, lambda: self.progress_var.set(0))
    
    def _convert_all_files(self):
        """转换所有文件（在后台线程中执行）"""
        total_files = len(self.excel_files)
        success_count = 0
        
        for i, file_path in enumerate(self.excel_files):
            try:
                file_name = os.path.basename(file_path)
                
                # 更新状态
                self.root.after(0, lambda: self.log_message(f"正在转换: {file_name}"))
                
                # 执行转换
                output_path = os.path.join(self.output_folder, file_name.replace('.xlsx', '.json'))
                self.converter.convert_excel_to_json(file_path, output_path)
                
                self.root.after(0, lambda: self.log_message(f"转换成功: {file_name}"))
                success_count += 1
                
            except Exception as e:
                self.root.after(0, lambda: self.log_message(f"转换失败: {file_name} - {str(e)}"))
            
            # 更新进度条
            progress = ((i + 1) / total_files) * 100
            self.root.after(0, lambda p=progress: self.progress_var.set(p))
        
        # 转换完成
        self.root.after(0, lambda: self.log_message(f"批量转换完成: {success_count}/{total_files} 成功"))
        self.root.after(0, lambda: self.progress_var.set(0))
    
    def clear_output(self):
        """清空输出文件夹"""
        if not self.output_folder_var.get():
            messagebox.showwarning("警告", "请先选择输出文件夹")
            return
        
        if messagebox.askyesno("确认", "确定要清空输出文件夹中的所有JSON文件吗？"):
            try:
                output_folder = self.output_folder_var.get()
                json_files = list(Path(output_folder).glob("*.json"))
                
                for json_file in json_files:
                    json_file.unlink()
                
                self.log_message(f"已删除 {len(json_files)} 个JSON文件")
            except Exception as e:
                messagebox.showerror("错误", f"清空输出文件夹失败: {str(e)}")


def main():
    """主函数"""
    root = tk.Tk()
    app = QuestionnaireGUI(root)
    root.mainloop()


if __name__ == "__main__":
    main()
